using System;
using System.Linq;
using Microsoft.Win32;

namespace unTroublemaker.Conditions
{
    public class RegistryCondition : SpecificationItemBase
    {
        private readonly RegistryKey _hive;
        private readonly  string _value;
        private readonly string _path;
        private readonly string _name;
        private readonly string _key;

        public RegistryCondition(string key, string value)
        {
            if (string.IsNullOrEmpty(key)) throw new ArgumentNullException("key");
            if (value == null) throw new ArgumentNullException("value");

            _key = key;

            if(!TryGetHive(key, out _hive))
                throw new Exception("Invalid registry hive: " + key);

            if(!TryGetKeyPathAndSubKey(key, out _path, out _name))
                throw new Exception("Invalid registry key path or sub key name: " + key);

            _value = value;
        }

        private bool TryGetKeyPathAndSubKey(string key, out string path, out string name)
        {
            var parts = key.Split('\\').Skip(1).ToArray();
            
            if (parts.Length < 2)
            {
                path = name = string.Empty;
                return false;
            }
            
            path = string.Join("\\", parts.Take(parts.Length - 1));
            name = parts.Last();
            return true;
        }

        private bool TryGetHive(string key, out RegistryKey hive)
        {
            var parts = key.Split('\\');
            var hiveName = parts.Length == 0 ? string.Empty : parts[0];

            switch (hiveName)
            {
                case "HKEY_LOCAL_MACHINE":
                    hive = Registry.LocalMachine;
                    return true;

                case "HKEY_CLASSES_ROOT":
                    hive = Registry.ClassesRoot;
                    return true;

                case "HKEY_CURRENT_CONFIG":
                    hive = Registry.CurrentConfig;
                    return true;

                case "HKEY_CURRENT_USER":
                    hive = Registry.CurrentUser;
                    return true;

                case "HKEY_USERS":
                    hive = Registry.Users;
                    return true;
                    
                default:
                    hive = Registry.LocalMachine;
                    return false;
            }
        }

        

        public override string DisplayName { get { return "Registry key " + _key + " = " + _value;} }

        protected override bool RunTest()
        {
            var key = _hive.OpenSubKey(_path, false);
            if (key == null)
            {
                StatusMessage = "Key did not exist: " + _path;
                return false;
            }

            var value = key.GetValue(_name, string.Empty).ToString();

            if (value.Equals(_value, StringComparison.InvariantCultureIgnoreCase))
                return true;

            StatusMessage = string.Format("Expected '{0}' actual '{1}'", _value, value);
            return false;
        }
    }
}